package cl.parser.internal;

import java.util.ArrayList;
import java.util.List;

import cl.parser.IParseNode;
import cl.parser.external.AssignmentOperatorNode;
import cl.parser.external.CloseParenNode;
import cl.parser.external.OpenParenNode;
import cl.parser.external.OperatorNode;

public class ExpressionNode extends InternalNode implements IFat {

    @Override
    public String prettyPrint(String indent) {
        String res = "";
        
        for(IParseNode p : children) {
            if(p instanceof ExpressionNode) {
                res += "(" + p.prettyPrint(indent) + ")";
            } else if(p instanceof OperatorNode) {
                res += " " + p.prettyPrint(indent) + " ";
            } else {
                res += p.prettyPrint(indent);
            }
        }
        
        return res.substring(0, res.length());
    }

    @Override
    protected List<IParseNode> getAllowed(IParseNode last, List<IParseNode> soFar) {
        List<IParseNode> allowed = new ArrayList<IParseNode>();
        
        if(last == null) {
            allowed.add(new OpenParenNode());
            allowed.add(new TermNode());
            allowed.add(new ExpressionNode());
        } else if(last instanceof OperatorNode || 
                  last instanceof AssignmentOperatorNode || 
                  last instanceof OpenParenNode) {
            allowed.add(new TermNode());
            allowed.add(new ExpressionNode());
        } else if(last instanceof TermNode || last instanceof ExpressionNode) {
            allowed.add(new OperatorNode());
            allowed.add(new AssignmentOperatorNode());
            
            if(soFar.get(0) instanceof OpenParenNode) {
                allowed.add(new CloseParenNode());
            }
        }
        
        return allowed;
    }

    @Override
    protected boolean isValid(IParseNode last, List<IParseNode> soFar) {
        if(!soFar.isEmpty() && soFar.get(0) instanceof OpenParenNode) {
            return last instanceof CloseParenNode;
        }
        
        return last instanceof TermNode || last instanceof ExpressionNode;
    }

    @Override
    public void loseWeight() {
        // remove  ( )
        if(children.get(0) instanceof OpenParenNode) {
            children.remove(0);
            children.remove(children.size() - 1);
        }
        
    }
}
